package taskhandler

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"cvevulner/common"
	"cvevulner/models"
	"cvevulner/util"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/config"
	"github.com/astaxie/beego/logs"
)

func CreateIssueData(issueTemp *models.IssueTemplate, cve models.VulnCenter,
	sc models.Score, resp map[string]interface{},
	path, assignee, issueType, labels, owner string) {
	issueTemp.CveId = cve.CveId
	issueTemp.CveNum = cve.CveNum
	issueTemp.OwnedComponent = cve.RepoName
	issueTemp.OwnedVersion = cve.CveVersion
	if issueTemp.TemplateId == 0 {
		issueTemp.MtAuditFlag = 1
		issueTemp.SaAuditFlag = 0
	}
	issueTemp.NVDScore = sc.NVDScore
	issueTemp.NVDVector = sc.NvectorVule
	issueTemp.CveBrief = cve.Description
	issueTemp.CveLevel = cve.CveLevel
	if resp != nil && len(resp) > 0 {
		issueTemp.IssueId = int64(resp["id"].(float64))
		issueTemp.IssueNum = resp["number"].(string)
		issueTemp.StatusName = resp["state"].(string)
		if strings.ToLower(resp["state"].(string)) == "open" ||
			resp["state"].(string) == "待办的" ||
			resp["state"].(string) == "开启的" {
			issueTemp.Status = 1
			issueTemp.StatusName = "open"
			issueTemp.IssueStatus = 1
		} else if strings.ToLower(resp["state"].(string)) == "started" ||
			strings.ToLower(resp["state"].(string)) == "progressing" ||
			strings.ToLower(resp["state"].(string)) == "进行中" {
			issueTemp.Status = 2
			issueTemp.StatusName = "progressing"
			issueTemp.IssueStatus = 3
		} else if strings.ToLower(resp["state"].(string)) == "closed" || resp["state"].(string) == "已完成" {
			issueTemp.Status = 3
			issueTemp.StatusName = "closed"
			issueTemp.IssueStatus = 2
		} else {
			if strings.ToLower(resp["state"].(string)) == "rejected" || resp["state"].(string) == "已拒绝" {
				issueTemp.StatusName = "rejected"
				issueTemp.Status = 4
			}
			if strings.ToLower(resp["state"].(string)) == "suspended" || resp["state"].(string) == "已挂起" {
				issueTemp.StatusName = "suspended"
				issueTemp.Status = 5
			}
			issueTemp.IssueStatus = 6
		}
	} else {
		issueTemp.IssueId = 0
		issueTemp.IssueNum = "nil"
		issueTemp.StatusName = "nil"
		issueTemp.Status = 0
	}
	issueTemp.Assignee = assignee
	issueTemp.IssueLabel = labels
	issueTemp.Owner = owner
	issueTemp.Repo = cve.PackName
	issueTemp.Title = cve.CveNum
	issueTemp.IssueType = issueType
	issueTemp.Collaborators = ""
	issueTemp.Milestone = ""
	issueTemp.Program = ""
	issueTemp.SecurityHole = 0
	logs.Info("CreateIssueData, Assemble issue, store template data in db: ", issueTemp)
}

func GetGiteeIssue(accessToken, owner, path, issueNum string) (error, map[string]interface{}) {
	var respBody map[string]interface{}
	url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/%v/issues/%v?access_token=%v", owner, path, issueNum, accessToken)
	if accessToken != "" && owner != "" && path != "" && issueNum != "" {
		issueInfo, err := util.HTTPGetCom(url)
		if err == nil && issueInfo != nil {
			err = json.Unmarshal(issueInfo, &respBody)
			if err != nil {
				logs.Error(err)
				return err, respBody
			}
			if respBody != nil && respBody["number"] != nil && respBody["number"].(string) == issueNum {
				return nil, respBody
			}
		} else {
			logs.Error("GetIssueNum, http request failed, url: ", url)
			return err, respBody
		}
	}
	return errors.New("error"), respBody
}

func GetRepoMember(accessToken, owner, path string) (error, []string, []string) {
	var respBody []map[string]interface{}
	assignLoginList := []string{}
	assignNameList := []string{}
	url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/%v/collaborators?access_token=%v&page=1&per_page=20", owner, path, accessToken)
	if accessToken != "" && owner != "" && path != "" {
		issueInfo, err := util.HTTPGetCom(url)
		if err == nil && issueInfo != nil {
			err = json.Unmarshal(issueInfo, &respBody)
			if err != nil {
				logs.Error(err)
				return err, assignLoginList, assignNameList
			}
			if len(respBody) > 0 {
				for _, rb := range respBody {
					if value, ok := rb["id"]; ok {
						if int(value.(float64)) > 0 {
							if rb["login"].(string) != "openeuler-ci-bot" {
								assignLoginList = append(assignLoginList, rb["login"].(string))
								assignNameList = append(assignNameList, rb["name"].(string))
							}
						}
					}
				}
				return nil, assignLoginList, assignNameList
			}
		} else {
			logs.Error("GetRepoMember, http request failed, url: ", url)
			return err, assignLoginList, assignNameList
		}
	}
	return errors.New("error"), assignLoginList, assignNameList
}

func OPenCheckWhetherIssue(cveNumber, repoPath, owner, accessToken string, organizationID int8) (bool, string) {
	vc := models.VulnCenter{CveNum: cveNumber, PackName: repoPath, OrganizationID: organizationID}
	vcErr := models.GetVulnCenterByCid(&vc, "CveNum", "PackName", "OrganizationID")
	if vcErr != nil {
		logs.Error("GetVulnCenterByCid, vcErr: ", vcErr, ",cveNum: ", cveNumber)
		return false, ""
	}
	issueTmp := models.IssueTemplate{}
	issueTmp.CveNum = cveNumber
	issueTmp.Repo = repoPath
	issueTmp.CveId = vc.CveId
	_ = models.GetIssueTemplateByColName(&issueTmp, "CveNum", "Repo", "CveId")
	if issueTmp.TemplateId > 0 && len(issueTmp.IssueNum) > 1 {
		issueErr, issueBody := GetGiteeIssue(accessToken, owner, repoPath, issueTmp.IssueNum)
		if issueErr == nil {
			logs.Info("OPenCheckWhetherIssue, Issue has been created,issueBody:", issueBody)
			return true, issueTmp.IssueNum
		}
	}
	return false, ""
}

func CreateIssueToGit(accessToken, owner, path, assignee string,
	cve models.VulnCenter, sc models.Score, brandArray []string) (string, error) {
	defer common.Catchs()
	var it models.IssueTemplate
	it.CveId = cve.CveId
	it.CveNum = cve.CveNum
	_, assignLoginList, _ := GetRepoMember(accessToken, owner, path)
	templateErr := models.GetIssueTemplateByColName(&it, "CveId", "CveNum")
	if cve.OrganizationID == 1 {
		sia := models.SpecIssueAssigness{PackageName: cve.PackName, Status: 1}
		specError := models.GetSpecIssueAssignee(&sia, "package_name", "status")
		if specError == nil && sia.Id > 0 {
			it.Assignee = sia.Assignee
			assignee = sia.Assignee
		}
	}
	assigneeGite := ""
	if cve.DataSource == 4 && cve.CveId == it.CveId && len(it.IssueNum) > 2 {
		logs.Info("Current data is synchronized")
	} else {
		if it.TemplateId > 0 && len(it.IssueNum) > 2 {
			issueErr, issueBody := GetGiteeIssue(accessToken, owner, path, it.IssueNum)
			if issueErr != nil {
				models.DeleteIssueTemplate(it.TemplateId)
				models.UpdateIssueStatus(cve, 0)
				return "", errors.New("Recreate issue")
			} else {
				if issueBody != nil && issueBody["assignee"] != nil {
					assigneeObj := issueBody["assignee"].(map[string]interface{})
					if assigneeObj != nil && assigneeObj["login"] != nil {
						assigneeGite = assigneeObj["login"].(string)
					}
				}
			}
		} else {
			logs.Error("CreateIssueToGit, GetIssueTemplateByColName, templateErr: ", templateErr, ",it: ", it)
		}
	}

	if it.TemplateId > 0 && len(it.IssueNum) > 2 {
		if it.Assignee == "" || len(it.Assignee) == 0 {
			it.Assignee = assignee
		}
		issueType := it.IssueType
		labels := ""
		if it.IssueLabel != "" && len(it.IssueLabel) > 1 {
			labels = it.IssueLabel
		} else {
			labels = beego.AppConfig.String("labelUnFix")
		}
		if accessToken != "" && owner != "" && path != "" {
			url := "https://gitee.com/api/v5/repos/" + owner + "/issues/" + it.IssueNum
			score := strconv.FormatFloat(sc.NVDScore, 'f', 1, 64)
			OpenEulerScore := strconv.FormatFloat(it.OpenEulerScore, 'f', 1, 64)
			if len(it.AffectedVersion) > 1 {
				brandArryTmp := strings.Split(it.AffectedVersion, ",")
				for _, brand := range brandArray {
					if !strings.Contains(it.AffectedVersion, brand+":") &&
						!strings.Contains(it.AffectedVersion, brand+"：") &&
						it.Status != 3 {
						brandArryTmp = append(brandArryTmp, brand+":")
					}
				}
				brandStr := strings.Join(brandArryTmp, ",")
				it.AffectedVersion = brandStr
			} else {
				if len(brandArray) > 0 {
					var brandArryTmp []string
					for _, brand := range brandArray {
						brandArryTmp = append(brandArryTmp, brand+":")
					}
					brandStr := strings.Join(brandArryTmp, ",")
					it.AffectedVersion = brandStr
				}
			}
			if len(assigneeGite) > 1 {
				it.Assignee = assigneeGite
			} else {
				if cve.OrganizationID == 1 && len(assignLoginList) > 0 {
					it.Assignee = assignLoginList[0]
				}
			}
			requestBody := CreateIssueBody(accessToken, owner, path, it.Assignee,
				cve, sc, OpenEulerScore, score, labels, it, 1, it.IssueType, "", brandArray)
			if requestBody != "" && len(requestBody) > 1 {
				logs.Info("CreateIssueToGit, Template data before issue creation: ", requestBody)
				resp, err := util.HTTPPatch(url, requestBody)
				if err != nil {
					logs.Error("CreateIssueToGit, Update issue failed, cveNum: ",
						cve.CveNum, ",err: ", err, ",url: ", url)
					return "", errors.New("调用gitee更新issue接口失败")
				}
				if _, ok := resp["id"]; !ok {
					logs.Error("CreateIssueToGit, Update issue failed, err: ", ok, ", url: ", url)
					return "", errors.New("调用gitee更新issue接口失败")
				}
				logs.Info("CreateIssueToGit, Update issue successfully, "+
					"cveNum: ", cve.CveNum, "issueNum: ", resp["number"].(string))
				// Structure data
				//var issueTemp models.IssueTemplate
				CreateIssueData(&it, cve, sc, resp, path, it.Assignee, issueType, labels, owner)
				// Store issue data
				issTempID, err := models.CreateIssueTemplate(&it)
				if err != nil {
					logs.Error("CreateIssueToGit, Failed to update data of issue template,"+
						" cveNum: ", cve.CveNum, ",err: ", err)
					//return "", nil
				}
				logs.Info("CreateIssueToGit, Successfully updated the data of the issue template, "+
					"issTempID: ", issTempID, ",cveNum: ", cve.CveNum)
			} else {
				logs.Info("CreateIssueToGit, No need to update the issue template and issue status, its: ", it)
			}
			// Update issue status
			models.UpdateIssueStatus(cve, 2)
			// Update score status
			models.UpdateIssueScore(cve, 2)
			// Update score record status
			models.UpdateIssueScoreRe(cve, 1)
		}
	} else {
		// Determine whether an issue has been created
		if cve.OrganizationID == 1 {
			gi := models.QueryGiteOriginIssue(cve.CveNum, cve.PackName, cve.OrganizationID)
			if len(gi) > 0 {
				flag := false
				for _, g := range gi {
					issueErr, issueRsp := GetGiteeIssue(accessToken, owner, path, g.Number)
					if issueErr != nil {
						var its models.IssueTemplate
						its.CveNum = cve.CveNum
						its.IssueNum = g.Number
						templateErr = models.GetIssueTemplateByColName(&its, "IssueNum", "CveNum")
						if its.TemplateId > 0 {
							models.DeleteIssueTemplate(its.TemplateId)
							flag = true
						}
					} else {
						var its models.IssueTemplate
						its.CveNum = cve.CveNum
						its.IssueNum = g.Number
						templateErr = models.GetIssueTemplateByColName(&its, "IssueNum", "CveNum")
						if its.TemplateId == 0 {
							its.CreateTime = time.Now()
							CreateIssueData(&its, cve, sc, issueRsp, path, assignee, issueRsp["issue_type"].(string), "", owner)
							// Store issue data
							issTempID, templateErr := models.InsertIssueTemplate(&its)
							if issTempID == 0 {
								logs.Error("templateErr: ", templateErr)
							}
						}
						return "", errors.New("Issue has been created")
					}
				}
				if flag {
					models.UpdateIssueStatus(cve, 0)
					return "", errors.New("Recreate issue")
				}
			}
			if len(assignLoginList) > 0 {
				assignee = assignLoginList[0]
			}
		}
		if it.TemplateId > 0 {
			models.DeleteIssueTemplate(it.TemplateId)
		}
		var issueType string
		issueType = CIssueType
		if cve.OrganizationID == 2 {
			issueType = GaussIssueType
		} else if cve.OrganizationID == 3 {
			issueType = MindSporeIssueType
		}
		labels := beego.AppConfig.String("labelUnFix")
		if accessToken != "" && owner != "" && path != "" {
			if models.FilterOldData(cve.CveNum) {
				return "", nil
			}
			if models.QueryCveOrigin(cve.CveNum, "update") {
				logs.Info("update cve is not create issue , cveNum :", cve.CveNum)
				return "", nil
			}
			var issueTemp models.IssueTemplate
			issueTemp.CreateTime = time.Now()
			CreateIssueData(&issueTemp, cve, sc, nil, path, assignee, issueType, labels, owner)
			// Store issue data
			issTempID, templateErr := models.InsertIssueTemplate(&issueTemp)
			if templateErr == nil && issTempID > 0 {
				url := "https://gitee.com/api/v5/repos/" + owner + "/issues"
				score := strconv.FormatFloat(sc.NVDScore, 'f', 1, 64)
				requestBody := CreateIssueBody(accessToken, owner, path, assignee,
					cve, sc, "", score, labels, it, 2, issueType, "", brandArray)
				logs.Info("CreateIssueToGit, isssue_body: ", requestBody)
				if requestBody != "" && len(requestBody) > 1 {
					resp, err := util.HTTPPost(url, requestBody)
					if err != nil {
						logs.Error("CreateIssueToGit, url: ", url, ", Failed to create issue, "+
							"cveNum: ", cve.CveNum, ", err: ", err, ",url:", url)
						models.DeleteIssueTemplate(issTempID)
						return "", errors.New("调用gitee的创建issue接口失败")
					}
					if _, ok := resp["id"]; !ok {
						logs.Error("CreateIssueToGit, Failed to create issue, "+
							"err: ", ok, ", url: ", url)
						models.DeleteIssueTemplate(issTempID)
						return "", errors.New("调用gitee的创建issue接口失败")
					}
					owner, accessToken = common.GetOwnerAndToken(cve.CveNum, cve.OrganizationID)
					//var issueTemps models.IssueTemplate
					issueTemp.TemplateId = issTempID
					CreateIssueData(&issueTemp, cve, sc, resp, path, assignee, issueType, labels, owner)
					if len(brandArray) > 0 {
						var brandArrayTmp []string
						for _, brand := range brandArray {
							brandArrayTmp = append(brandArrayTmp, brand+":")
						}
						brandStr := strings.Join(brandArrayTmp, ",")
						issueTemp.AffectedVersion = brandStr
						issueTemp.AbiVersion = brandStr
						issueTemp.SaAuditFlag = 0
					} else {
						issueTemp.SaAuditFlag = 1
					}
					// Store issue data
					issTempIDx, idxErr := models.UpdateIssueTemplateAll(&issueTemp)
					if idxErr != nil {
						logs.Error("CreateIssueToGit, Failed to create data for issue template, "+
							"cveNum: ", cve, ",err: ", err)
						//models.DeleteIssueTemplate(issTempID)
						return "", errors.New("内部错误, 模板存储失败")
					}
					logs.Info("CreateIssueToGit, The data of the issue template was successfully, "+
						"created, issTempID: ", issTempIDx, "cveNum: ", cve.CveNum)
					// Create issue comment
					affectedVersion := ""
					if len(brandArray) > 0 {
						for i, brand := range brandArray {
							if brand == "" || len(brand) < 2 {
								continue
							}
							brandx := ""
							if cve.OrganizationID == 1 {
								brandx = common.BranchVersionRep(brand)
								brandx = OrgRepoParams(cve.PackName, brandx)
							} else {
								brandx = brand
							}
							affectedVersion = affectedVersion + strconv.Itoa(i+1) + "." + brandx + ":\n"
						}
					} else {
						affectedVersion = affectedVersion + "\n"
					}
					issueNum := resp["number"].(string)
					errx := CreateIssueComment(accessToken, owner, path, assignee, cve, issueNum, affectedVersion, assignLoginList)
					logs.Info("CreateIssueToGit, Issue comment creation result, err: ", errx)
					if cve.OrganizationID == 1 {
						// Trigger third-party data generation
						agencyUrl := beego.AppConfig.String("cveagency::url")
						agencyReq := make(map[string]interface{}, 0)
						agencyReq["CveNum"] = issueTemp.CveNum
						agencyReq["PackName"] = issueTemp.OwnedComponent
						agencyReq["PackVersion"] = issueTemp.OwnedVersion
						if len(brandArray) > 0 {
							agencyReq["AffectBranch"] = strings.Join(brandArray, " ")
						} else {
							agencyReq["AffectBranch"] = ""
						}
						agencyReq["IssueNumber"] = issueTemp.IssueNum
						util.HTTPPostCom(agencyReq, agencyUrl)
					}
					// Send gitee private message
					content := fmt.Sprintf("%v 仓库有新的CVE和安全问题的ISSUE被 cve-manager 创建,CVE编号: %v, 请及时处理.", path, cve.CveNum)
					SendPrivateLetters(accessToken, content, assignee)
					//issueNum := resp["number"].(string)
					issueID := int64(resp["id"].(float64))
					err = CreateDepositHooks(accessToken, owner, path, cve, issueNum, issueID)
					if err != nil {
						logs.Error("CreateIssueToGit, Failed to create hooks, cveNum: ", cve.CveNum, "err: ", err)
						return "", errors.New("创建webhook失败")
					}
					logs.Info("CreateIssueToGit, Create hooks successfully, cveNum: ", cve.CveNum)
					// Update issue status
					models.UpdateIssueStatus(cve, 2)
					// Update score status
					models.UpdateIssueScore(cve, 2)
					// Update score record status
					models.UpdateIssueScoreRe(cve, 1)
				} else {
					models.DeleteIssueTemplate(issTempID)
				}
			} else {
				logs.Error("CreateIssueToGit, Repeat issue, cve: ", cve,
					", templateErr: ", templateErr)
				return "", nil
			}
		}
	}
	branchs := ""
	if len(brandArray) > 0 {
		for _, b := range brandArray {
			if b != "" && len(b) > 1 {
				branchs = branchs + b + "/"
			}
		}
		if branchs != "" && len(branchs) > 1 {
			branchs = branchs[:len(branchs)-1]
		}
	}
	// Store security bulletin related information
	var sec models.SecurityNotice
	CreateSecNoticeData(&sec, cve, path, branchs, sc.NVDScore)
	secID, noticeErr := models.UpdateSecNotice(&sec)
	if noticeErr != nil {
		logs.Error("CreateIssueToGit, Failed to update security information,"+
			"CveNum: ", cve.CveNum, "path: ", path, "err: ", noticeErr)
		return "", nil
	}
	logs.Info("CreateIssueToGit, Update security information successfully, "+
		"secID: ", secID, "cveNum: ", cve.CveNum)
	return "", nil
}

func UpdateIssueToGit(accessToken, owner, path string,
	cve models.VulnCenter, its models.IssueTemplate) (string, error) {
	logs.Info("UpdateIssueToGit, Update template request parameters: cve: ", cve,
		",its: ", its, ", owner: ", owner, ",path: ", path)
	if its.Status == 4 || its.Status == 5 {
		logs.Error("UpdateIssueToGit, "+
			"The current issue has been suspended/rejected and will not be processed, its: ", its)
		models.UpdateIssueStatus(cve, 2)
		return "", errors.New("The current issue has been suspended/rejected and will not be processed")
	}
	owner, accessToken = common.GetOwnerAndToken(cve.CveNum, cve.OrganizationID)
	if cve.OrganizationID == 2 {
		if len(path) < 2 {
			path = beego.AppConfig.String("opengauss::gauss_issue_path")
		}
	}
	assigneeGite := ""
	if cve.DataSource == 4 && cve.CveId == its.CveId && len(its.IssueNum) > 2 {
		logs.Info("Current data is synchronized")
	} else {
		if its.IssueNum != "" && len(its.IssueNum) > 2 {
			issueErr, issueBody := GetGiteeIssue(accessToken, owner, path, its.IssueNum)
			if issueErr != nil {
				models.DeleteIssueTemplate(its.TemplateId)
				models.UpdateIssueStatus(cve, 0)
				return "", errors.New("Recreate issue")
			} else {
				if issueBody != nil {
					if issueBody != nil && issueBody["assignee"] != nil {
						assigneeObj := issueBody["assignee"].(map[string]interface{})
						if assigneeObj != nil && assigneeObj["login"] != nil {
							assigneeGite = assigneeObj["login"].(string)
						}
					}
				}
			}
		} else {
			models.DeleteIssueTemplate(its.TemplateId)
			models.UpdateIssueStatus(cve, 0)
			return "", errors.New("Recreate issue")
		}
	}
	//labels := its.IssueLabel
	if cve.OrganizationID == 1 {
		sia := models.SpecIssueAssigness{PackageName: cve.PackName, Status: 1}
		specError := models.GetSpecIssueAssignee(&sia, "package_name", "status")
		if specError == nil && sia.Id > 0 {
			its.Assignee = sia.Assignee
		}
	}
	labels := ""
	if its.IssueLabel != "" && len(its.IssueLabel) > 1 {
		labels = its.IssueLabel
	} else {
		labels = beego.AppConfig.String("labelUnFix")
	}
	pkgList, err := models.QueryPackageByCveId(its.CveId)
	pkgLink := ""
	var brandArray []string
	if err == nil && len(pkgList) > 0 {
		for _, p := range pkgList {
			pkgLink = pkgLink + fmt.Sprintf(`[%v](%v)\r\n`, p.PackName, p.PackUrl)
		}
	}
	if accessToken != "" && owner != "" && path != "" {
		url := "https://gitee.com/api/v5/repos/" + owner + "/issues/" + its.IssueNum
		score := strconv.FormatFloat(its.NVDScore, 'f', 1, 64)
		OpenEulerScore := strconv.FormatFloat(its.OpenEulerScore, 'f', 1, 64)
		var sc models.Score
		sc, scok := models.QueryScoreByCveId(cve.CveId)
		if !scok {
			logs.Error("UpdateIssueToGit, Score does not exist, cve: ", cve, cve.CveNum)
		}
		if len(assigneeGite) > 1 {
			its.Assignee = assigneeGite
		}
		requestBody := CreateIssueBody(accessToken, owner, path, its.Assignee,
			cve, sc, OpenEulerScore, score, labels, its, 3, its.IssueType, pkgLink, brandArray)
		logs.Info("UpdateIssueToGit, isssue_body: ", requestBody)
		if requestBody != "" && len(requestBody) > 1 {
			resp, err := util.HTTPPatch(url, requestBody)
			if err != nil {
				logs.Error("UpdateIssueToGit, Update issue failed, cveNum: ", cve.CveNum, "err: ", err)
				return "", errors.New("调用gitee更新issue的接口失败")
			}
			if _, ok := resp["id"]; !ok {
				logs.Error("UpdateIssueToGit, Failed to create issue, err: ", ok, "url: ", url, cve.CveNum)
				return "", errors.New("调用gitee更新issue的接口失败")
			}
			// Store security bulletin related information
			var sec models.SecurityNotice
			CreateSecNoticeData(&sec, cve, path, its.AffectedVersion, its.OpenEulerScore)
			secId, err := models.UpdateSecNotice(&sec)
			if err != nil {
				logs.Error("UpdateIssueToGit, Failed to update security information, "+
					"CveNum: ", cve.CveNum, ",path: ", path, ",err: ", err)
				return "", errors.New("内部错误, 数据错误")
			} else {
				logs.Info("UpdateIssueToGit, Update security information successfully, "+
					"secId: ", secId, ",cveNum: ", cve.CveNum)
			}
		}
	}
	return "", nil
}

func CreateIssueHookData(issHook *models.IssueHooks, resp map[string]interface{},
	path, owner string, issueNum string, issueId, cveId int64) *models.IssueHooks {
	issHook.CveId = cveId
	issHook.IssueId = issueId
	issHook.IssueNum = issueNum
	issHook.HookId = int64(resp["id"].(float64))
	issHook.Owner = owner
	issHook.Repo = path
	issHook.CreateTime = common.GetCurTime()
	issHook.UpdateTime = common.GetCurTime()
	issHook.Status = 1
	issHook.HookUrl = resp["url"].(string)
	if resp["push_events"].(bool) == true {
		issHook.PushEvent = 1
	} else {
		issHook.PushEvent = 0
	}
	if resp["tag_push_events"].(bool) == true {
		issHook.TagPushEvent = 1
	} else {
		issHook.TagPushEvent = 0
	}
	if resp["issues_events"].(bool) == true {
		issHook.IssueEvent = 1
	} else {
		issHook.IssueEvent = 0
	}
	if resp["note_events"].(bool) == true {
		issHook.NoteEvent = 1
	} else {
		issHook.NoteEvent = 0
	}
	if resp["merge_requests_events"].(bool) == true {
		issHook.MergeRequestEvent = 1
	} else {
		issHook.MergeRequestEvent = 0
	}
	return issHook
}

func PatchWebHooks(accessToken, owner, path, hookurl, pwd, issueNum,
	hookId string, issueId, cveId int64) error {
	if accessToken != "" && owner != "" && path != "" {
		url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks/" + hookId
		push_events := "true"
		tag_push_events := "true"
		issues_events := "true"
		note_events := "true"
		merge_requests_events := "true"
		requestBody := fmt.Sprintf(`{
					"access_token": "%s",
					"url": "%s", 
					"password": "%s",
					"push_events": "%s",
					"tag_push_events": "%s",
					"issues_events": "%s",
					"note_events": "%s",
					"merge_requests_events": "%s"
					}`, accessToken, hookurl, pwd, push_events,
			tag_push_events, issues_events, note_events, merge_requests_events)
		logs.Info("PatchWebHooks, hook_body: ", requestBody)
		resp, err := util.HTTPPatch(url, requestBody)
		if err != nil {
			logs.Error("PatchWebHooks, Failed to update webhook, url: ", url, ", err: ", err)
			return err
		}
		if _, ok := resp["id"]; !ok {
			logs.Error("PatchWebHooks, Failed to update webhook, err: ", ok, ", url: ", url)
			return errors.New("更新仓库 hook失败")
		}
		if resp["password"].(string) == pwd {
			var issHook models.IssueHooks
			CreateIssueHookData(&issHook, resp,
				path, owner, issueNum, issueId, cveId)
			hookId, err := models.CreateDepositHooks(&issHook)
			if err != nil {
				logs.Error("PatchWebHooks, Failed to update webhook, repo: ", path, ", err: ", err)
				return nil
			} else {
				logs.Info("PatchWebHooks, Update webhook successfully, hookId: ", hookId, "repo: ", path)
			}
		}
		return nil
	}
	return errors.New("更新仓库 hook失败")
}

func PostWebHooks(accessToken, owner, path, hookurl, pwd, issueNum string, issueId, cveId int64) error {
	if accessToken != "" && owner != "" && path != "" {
		url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks"
		push_events := "true"
		tag_push_events := "true"
		issues_events := "true"
		note_events := "true"
		merge_requests_events := "true"
		requestBody := fmt.Sprintf(`{
			"access_token": "%s",
			"url": "%s", 
			"password": "%s",
			"push_events": "%s",
			"tag_push_events": "%s",
			"issues_events": "%s",
			"note_events": "%s",
			"merge_requests_events": "%s"
			}`, accessToken, hookurl, pwd, push_events,
			tag_push_events, issues_events, note_events, merge_requests_events)
		logs.Info("hook_body: ", requestBody)
		resp, err := util.HTTPPost(url, requestBody)
		if err != nil {
			logs.Error("PatchWebHooks, Failed to create webhook, url: ", url,
				", cveId:", cveId, ",err: ", err)
			return err
		}
		if _, ok := resp["id"]; !ok {
			logs.Error("PatchWebHooks, Failed to create webhook, err: ", ok, "url: ", url)
			return errors.New("创建仓库hook失败")
		}
		if resp["password"].(string) == pwd {
			var issHook models.IssueHooks
			CreateIssueHookData(&issHook, resp,
				path, owner, issueNum, issueId, cveId)
			// Store issue data
			hookId, err := models.CreateDepositHooks(&issHook)
			if err != nil {
				logs.Error("PatchWebHooks, Failed to create webhook, path: ", path, ", err: ", err)
				return err
			} else {
				logs.Info("PatchWebHooks, Create webhook successfully, hookId: ", hookId, ", path: ", path)
			}
		}
		return nil
	}
	return errors.New("创建仓库hook失败")
}

func CreateDepositHooks(accessToken string, owner string, path string,
	cve models.VulnCenter, issueNum string, issueId int64) error {
	createFlag, ok := beego.AppConfig.Int("hook::create_hook")
	if ok != nil {
		createFlag = 1
	}
	if createFlag == 1 {
		var ih models.IssueHooks
		ih.CveId = cve.CveId
		ih.IssueNum = issueNum
		ih.Owner = owner
		ih.Status = 1
		ih.Repo = path
		BConfig, err := config.NewConfig("ini", "conf/app.conf")
		if err != nil {
			logs.Error("CreateDepositHooks, config init,  error:", err)
			return err
		}
		pwd := BConfig.String("hook::hookpwd")
		hookurl := BConfig.String("hook::hookurl")
		ihs, errh := models.GetIssueHook(&ih)
		if errh {
			hookExist := false
			for _, wh := range ihs {
				if wh.HookUrl == hookurl {
					hookExist = true
					hookId := strconv.FormatInt(wh.HookId, 10)
					patchErr := PatchWebHooks(accessToken, owner, path, hookurl,
						pwd, issueNum, hookId, issueId, cve.CveId)
					if patchErr == nil {
						logs.Info("CreateDepositHooks, owner: ", owner,
							",repo: ", path, ",webhook updated successfully")
					} else {
						logs.Error("CreateDepositHooks, owner: ", owner,
							",repo: ", path, ",patchErr: ", patchErr)
					}
				}
			}
			if !hookExist {
				postErr := PostWebHooks(accessToken, owner, path,
					hookurl, pwd, issueNum, issueId, cve.CveId)
				if postErr == nil {
					logs.Info("CreateDepositHooks, owner: ", owner,
						",repo: ", path, ",webhook created successfully")
				} else {
					logs.Error("CreateDepositHooks, owner: ", owner,
						",repo: ", path, ",postErr: ", postErr)
				}
			}
		} else {
			postErr := PostWebHooks(accessToken, owner, path,
				hookurl, pwd, issueNum, issueId, cve.CveId)
			if postErr == nil {
				logs.Info("CreateDepositHooks, owner: ", owner,
					",repo: ", path, ",webhook created successfully")
			} else {
				logs.Error("CreateDepositHooks, owner: ", owner,
					",repo: ", path, ", postErr: ", postErr)
			}
		}
	}
	return nil
}

func CreateIssueComment(accessToken, owner, path, assignee string,
	cve models.VulnCenter, issueNum, affectedVersion string, assignLoginList []string) error {
	if accessToken != "" && owner != "" && path != "" {
		url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/issues/" + issueNum + "/comments"
		BConfig, err := config.NewConfig("ini", "conf/app.conf")
		if err != nil {
			logs.Error("CreateIssueComment, config init, error:", err)
			return err
		}
		commentCmd := BConfig.String("reflink::comment_cmd")
		commentBody := ""
		if cve.OrganizationID == 4 {
			commentCmd = BConfig.String("reflink::looKeng_comment_cmd")
			commentBody = LooKengCommentTemplate(assignee, commentCmd, affectedVersion)
		} else if cve.OrganizationID == 3 {
			commentCmd = BConfig.String("reflink::spore_comment_cmd")
			commentBody = SporeCommentTemplate(assignee, commentCmd, affectedVersion)
		} else if cve.OrganizationID == 2 {
			commentCmd = BConfig.String("reflink::gauss_comment_cmd")
			commentBody = GaussCommentTemplate(assignee, commentCmd, affectedVersion)
		} else {
			commentBody = CommentTemplate(assignee, commentCmd, affectedVersion, path, assignLoginList)
		}
		requestBody := fmt.Sprintf(`{
			"access_token": "%s",
			"body": "%s"
			}`, accessToken, commentBody)
		logs.Info("CreateIssueComment, create issue comment body: ", requestBody)
		resp, err := util.HTTPPost(url, requestBody)
		if err != nil {
			logs.Error("CreateIssueComment, Failed to create issue comment, url: ", url,
				", cveId", cve.CveId, ",issueNum: ", issueNum, ",err: ", err)
			return err
		}
		if _, ok := resp["id"]; !ok {
			logs.Error("CreateIssueComment, Failed to create issue comment, err: ", ok, ", url: ", url)
			return errors.New("创建issue评论失败")
		}
		commentID := int64(resp["id"].(float64))
		models.UpdateIssueCommentId(issueNum, cve.CveNum, commentID)
	}
	return nil
}

func AddAffectBrands(branchVersion string) string {
	branchs := ""
	if branchVersion != "" && len(branchVersion) > 1 {
		brandsGroup := strings.Split(branchVersion, ",")
		if len(brandsGroup) > 0 {
			for _, brand := range brandsGroup {
				if brand == "" || len(brand) < 2 {
					continue
				}
				brand = common.BranchVersionRep(brand)
				brandList := strings.Split(brand, ":")
				if len(brandList) > 1 {
					prams := strings.Replace(brandList[1], " ", "", -1)
					if prams == "受影响" {
						branchs += brandList[0] + "/"
					}
				} else {
					brandList := strings.Split(brand, "：")
					if len(brandList) > 1 {
						prams := strings.Replace(brandList[1], " ", "", -1)
						if prams == "受影响" {
							branchs += brandList[0] + "/"
						}
					}
				}
			}
		}
	}
	if branchs != "" && len(branchs) > 1 {
		branchs = branchs[:len(branchs)-1]
	}
	return branchs
}

func CreateSecNoticeData(sec *models.SecurityNotice, iss models.VulnCenter,
	path, branchVersion string, opScore float64) {
	branchs := AddAffectBrands(branchVersion)
	sec.CveId = iss.CveId
	sec.CveNum = iss.CveNum
	opScoreLeve := models.OpenEulerScoreProc(opScore)
	if len(iss.RepoName) < 1 {
		iss.RepoName = iss.PackName
	}
	sec.Introduction = "An update for " + iss.RepoName + " is now available for " + branchs + "."
	if iss.OrganizationID == 4 {
		sec.Theme = sec.Introduction[:len(sec.Introduction)-1] + ".\n\n" + "openLooKeng Security has rated this" +
			" update as having a security impact of " + strings.ToLower(opScoreLeve) + ". A Common Vunlnerability" +
			" Scoring System(CVSS)base score,which gives a detailed severity rating," +
			" is available for each vulnerability from the CVElink(s) in the References section."
	} else if iss.OrganizationID == 3 {
		sec.Theme = sec.Introduction[:len(sec.Introduction)-1] + ".\n\n" + "MindSpore Security has rated this" +
			" update as having a security impact of " + strings.ToLower(opScoreLeve) + ". A Common Vunlnerability" +
			" Scoring System(CVSS)base score,which gives a detailed severity rating," +
			" is available for each vulnerability from the CVElink(s) in the References section."
	} else if iss.OrganizationID == 2 {
		sec.Theme = sec.Introduction[:len(sec.Introduction)-1] + ".\n\n" + "openGauss Security has rated this" +
			" update as having a security impact of " + strings.ToLower(opScoreLeve) + ". A Common Vunlnerability" +
			" Scoring System(CVSS)base score,which gives a detailed severity rating," +
			" is available for each vulnerability from the CVElink(s) in the References section."
	} else {
		sec.Theme = sec.Introduction[:len(sec.Introduction)-1] + ".\n\n" + "openEuler Security has rated this" +
			" update as having a security impact of " + strings.ToLower(opScoreLeve) + ". A Common Vunlnerability" +
			" Scoring System(CVSS)base score,which gives a detailed severity rating," +
			" is available for each vulnerability from the CVElink(s) in the References section."
	}
	sec.AffectProduct = branchs
}

func CreateBrandAndTags(accessToken, owner, path string, organizationID int8) []string {
	tagsList := make([]string, 0)
	branchList, errBrands := GetBranchesInfo(accessToken, owner, path, organizationID)
	if branchList == nil || len(branchList) == 0 {
		logs.Error("ProcIssue, Failed to obtain branch information,CveNum: ", "",
			", path: ", path, ", err: ", errBrands)
	}
	if len(branchList) > 0 {
		tagList, tagErr := GetTagsInfo(accessToken, owner, path, organizationID)
		if tagList == nil || len(tagList) == 0 {
			logs.Error("GetTagsInfo, Failed to obtain tag information, path: ", path, ",owner:", owner, ", err: ", tagErr)
			tagsList = append(tagsList, "master")
		} else {
			if organizationID == 3 {
				for _, branch := range branchList {
					// delete data
					models.DelMindSporeBrandTagsByBrand(branch, path)
					bl := common.StripStrReg(branch)
					for _, tags := range tagList {
						if strings.Contains(tags, bl) {
							mbt := models.MindSporeBrandTags{PackageName: path, Brand: branch, Tags: tags, CreateTime: common.GetCurTime()}
							spId, spErr := models.InsertMindSporeBrandTags(&mbt)
							if spErr != nil {
								logs.Error(spId, spErr)
								continue
							}
							tagsList = append(tagsList, tags)
						}
					}
					if branch == "master" {
						mbt := models.MindSporeBrandTags{PackageName: path, Brand: branch, Tags: branch, CreateTime: common.GetCurTime()}
						spId, spErr := models.InsertMindSporeBrandTags(&mbt)
						if spErr != nil {
							logs.Error(spId, spErr)
							continue
						}
						tagsList = append(tagsList, branch)
					}
				}
			} else if organizationID == 4 {
				tagsList = append(tagsList, tagList...)
				tagsList = append(tagsList, "master")
			}
		}
	}
	tagsList = common.RemoveDupString(tagsList)
	logs.Info("CreateBrandAndTags, tagsList: ", tagsList)
	return tagsList
}
